;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Classe delle immagini
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;







(defgeneric image-set-pixel (img i j value)
  (:documentation "Imposta il valore del pixel (i,j) a value"))

(defmethod image-set-pixel ((img image) (i integer) (j integer) (value number))
  (setf (aref (image-pixels img) i j) value))

(defgeneric save-image-to-file (img filename fileformat)
  (:documentation "Salva immagine in formato PGM"))

(defmethod save-image-to-file ((img image) filename (fileformat (eql 'pgm)))
  (with-open-file (out filename :direction :output)
    (with-standard-io-syntax
      (let ((m (image-num-rows img))
	    (n (image-num-cols img)))
	(format out "P2~%#~%~A~%~A~%255~%" m n)
	(loop for i from 0 to (- m 1) do
	     (loop for j from 0 to (- n 1) do
		  (format out "~A~%" (image-get-pixel  img i j))))))))





;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Classe delle formiche
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;







;(defmethod ant-path-energy :before ((anty ant))
;  (setf (slot-value anty 'path-energy) 
;	(loop for quark-element in (ant-path anty) summing (quark-value quark-element))))


(defgeneric choose-pixel (anty img1 img2 i j)
  (:documentation "Scelta del pixel i j per la formica anty sulle immmagini img1 e img2"))

(defmethod choose-pixel ((anty ant) (img1 image) (img2 image) (i (eql 0)) (j (eql 0)))
  (let* (;vecchi traccia di feromone
	 (pheromone (aref *pheromone* i j))
	 ;quarks del pheromone
	 (quark-trail (get-quarks-from-pheromone pheromone))
	 ;elenco dei pixel di img2 che hanno lo stesso valore del pixel (0,0) di img1
	 ;ma che ancora non stanno nella traccia di pheromone
	 (nuovi-pixel (remove-if #'(lambda (x) (gethash x pheromone)) (locate-color img2 (image-get-pixel img1 i j))))
	 ;quarks ottenuti dai nuovi pixels
	 (new-quarks (loop for pixel in nuovi-pixel 
			collecting (create-quark (create-shift (first pixel) (second pixel)) *default-pheromone*)))
	 (lista-finale (append quark-trail new-quarks)))
    lista-finale))


(defgeneric update-quark-value (quark img1 img2 base-pixel anty alpha beta)
  (:documentation "Calcolo di pheromone ed euristica per un quark"))


(defmethod update-quark-value ((quarky quark) (img1 image) (img2 image) (base-pixel shift) (anty ant) (alpha number) (beta number))
  (let* ((sh (quark-shift quarky))
	 (ph-value (quark-value quarky))
	 (energy-value (energy img1 img2 base-pixel sh anty)))
    (* (expt ph-value alpha) (expt (eta energy-value 100000 1) beta))))


(defun get-quarks-from-pheromone (pheromone)
  (loop for key being the hash-keys of pheromone using (hash-value value)
					collecting (create-quark (create-shift (first key) (second key)) value)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



  







;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Classe dei quarks ((i,j),value)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;














;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Euristica e funzioni di supporto
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;






